package de.dhbw.karlsruhe.picsim.gui;

import de.dhbw.karlsruhe.picsim.model.cpu.FileMutable;
import de.dhbw.karlsruhe.picsim.model.memory.FileAddress;
import de.dhbw.karlsruhe.picsim.model.memory.FileMemoryMutable;
import de.dhbw.karlsruhe.picsim.model.memory.RegisterValue;
import de.dhbw.karlsruhe.picsim.model.memory.impl.FileAddressImpl;
import de.dhbw.karlsruhe.picsim.util.impl.Addresses;
import de.dhbw.karlsruhe.picsim.util.impl.Lengths;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.table.AbstractTableModel;

/**
 * Created by IntelliJ IDEA.
 * User: goesen
 * Date: Apr 15, 2010
 * Time: 10:03:12 PM
 */
final class SwingFileMemory extends AbstractTableModel {
    private static final Log log = LogFactory.getLog(SwingFileMemory.class);
    private final FileMemoryMutable fileMemory;
    private final int offset;

    SwingFileMemory(@NotNull final FileMemoryMutable fileMemory, final int offset) {
        this.fileMemory = fileMemory;
        this.offset = offset;
    }

    @Override
    public String getColumnName(final int column) {
        if (column == 0) {
            return "Adresse";
        } else if (column == 1) {
            return "Decimal";
        } else if (column == 2) {
            return "Hex";
        }
        log.warn("Illegal column " + column);
        return super.getColumnName(column);
    }

    @Override
    public int getRowCount() {
        return Lengths.FILE_MEMORY_SIZE / 2;
    }


    @Override
    public int getColumnCount() {
        return 3;
    }

    @SuppressWarnings({"RefusedBequest"})
    @Override
    public boolean isCellEditable(final int rowIndex, final int columnIndex) {
        return (columnIndex == 1 || columnIndex == 2) && isImplemented(rowIndex);
    }

    private boolean isImplemented(final int rowIndex) {
        return !Addresses.isUnimplemented(getAddress(rowIndex));
    }

    @Override
    public void setValueAt(@Nullable final Object aValue, final int rowIndex, final int columnIndex) {
        //nur wenn ein Sinnvoller Wert ankommt und es um die Datenspalte geht
        if (aValue != null && (columnIndex == 1 || columnIndex == 2)) {
            final FileMutable file = fileMemory.getFile(getAddress(rowIndex));
            //wird der neue Wert ins File geschrieben
            file.setValue((RegisterValue) aValue);
            fireTableDataChanged();
        } else if (aValue == null) {
            log.info("User input for FileAddress " + (rowIndex + offset) + " was discarded");
        }


    }

    @Nullable
    @Override
    public Object getValueAt(final int rowIndex, final int columnIndex) {
        final FileAddress fileAddress = getAddress(rowIndex);
        if (columnIndex == 0) {
            return fileAddress;
        } else if (columnIndex == 1 || columnIndex == 2) {
            return fileMemory.getFile(fileAddress).getData();
        }

        log.warn("Illegal column " + columnIndex);
        return null;
    }

    private FileAddress getAddress(final int rowIndex) {
        return FileAddressImpl.createUnSafe(rowIndex + offset);
    }

}
